<template>
  <div class="canvasMain" v-loading="loading" id="canvasMainId" @dblclick="domMouseTwoClicked">
    <!-- 知识操作对话栏 -->
    <div id="nodeDialogId" class="nodeDialog">
      <div class="logined">
        <button v-if="!isCollected()" @click="collect()">收藏节点</button>
        <button v-else class="notButton">节点已收藏</button>
      </div>
      <div class="power" v-if="isPower()">
        <el-popover placement="top" :width="160" ref="popoverNode">
          <p>该操作会永久删除节点,您确定吗?</p>
          <div style="text-align: right; margin: 0">
            <el-button size="mini" type="text" @click="popoverNodeClose()">取消</el-button>
            <el-button type="primary" size="mini" @click="deleteNodeClick()">确定</el-button>
          </div>
          <template #reference>
            <button>删除节点</button>
          </template>
        </el-popover>
        <button @click="relative()">节点连接</button>
        <button @click="showEditNodeDialog()">编辑节点</button>
      </div>
      <button @click="nodeTags()">节点简介</button>
      <button @click="cancel()">取消</button>
    </div>

    <!-- 知识联系操作对话栏 -->
    <div id="linkDialogId" class="linkDialog">
      <el-popover placement="top" :width="160" ref="popoverLink">
        <p>该操作会永久删除连线,您确定吗?</p>
        <div style="text-align: right; margin: 0">
          <el-button size="mini" type="text" @click="popoverLinkClose()">取消</el-button>
          <el-button type="primary" size="mini" @click="deleteLinkClick()">确定</el-button>
        </div>
        <template #reference>
          <button>删除连线</button>
        </template>
      </el-popover>
      <button @click="cancelLink()">取消</button>
    </div>

    <!-- 知识修改操作对话栏 -->
    <el-dialog title="修改知识节点" :visible.sync="editNodeDialog" width="50%" :close-on-click-modal="false">
      <el-form :model="editNode" label-width="140px">
        <el-form-item label="所属类别">
          <el-select v-model="editNode.classId" placeholder="请选择所属类别">
            <el-option :label="item.className" :value="item.id" v-for="item in categories" :key="item.id"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="知识名称">
          <el-input v-model="editNode.knowledgeName"></el-input>
        </el-form-item>
        <el-form-item label="标签集(用|分开)">
          <el-input v-model="editNode.knowledgeTag"></el-input>
        </el-form-item>
        <el-form-item label="大小">
          <el-input v-model="editNode.size"></el-input>
        </el-form-item>
        <el-form-item label="知识内容">
          <el-input v-model="editNode.knowledgeContent" type="textarea" :rows="3"></el-input>
        </el-form-item>
         <el-form-item label="颜色(rgb)">
           <el-color-picker v-model="editNode.color" :color-format="'rgb'" :show-alpha="false"></el-color-picker>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="editNodeDialog = false">取 消</el-button>
          <el-button type="primary" @click="editNoded ()">确 定</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 添加知识按钮和知识类别下拉菜单 -->
    <div class="addNode">
      <el-button v-if="isPower()" type="primary" icon="el-icon-plus" circle @click="addNodeDialog = true" size="mini"></el-button>
      <el-dropdown @command="handleCommand" size="mini" placement="top">
        <el-button type="primary" circle icon="el-icon-arrow-down" size="mini"></el-button>
        <template #dropdown>
          <el-dropdown-menu>
            <el-dropdown-item command="0">ALL</el-dropdown-item>
            <el-dropdown-item :command="cate.id" v-for="cate in categories" :key="cate.id">{{cate.className}}</el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
    </div>

    <!-- 添加知识对话框 -->
    <el-dialog title="添加知识节点" :visible.sync="addNodeDialog" width="50%" @close="addDialogClose()" :close-on-click-modal="false">
      <el-form :model="addNodeForm" label-width="140px">
        <el-form-item label="所属类别">
          <el-select v-model="addNodeForm.classId" placeholder="请选择所属类别">
            <el-option :label="item.className" :value="item.id" v-for="item in categories" :key="item.id"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="知识名称">
          <el-input v-model="addNodeForm.knowledgeName"></el-input>
        </el-form-item>
        <el-form-item label="大小">
          <el-input v-model="addNodeForm.size"></el-input>
        </el-form-item>
        <el-form-item label="颜色(rgb)">
          <el-color-picker v-model="addNodeForm.color" :color-format="'rgb'" :show-alpha="false"></el-color-picker>
        </el-form-item>
        <el-form-item label="知识内容">
          <el-input v-model="addNodeForm.knowledgeContent" type="textarea" :rows="3"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="addNodeDialog = false">取 消</el-button>
          <el-button type="primary" @click="addNode ()">确 定</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 知识详细信息 -->
    <el-dialog :title="nodeInfo.label" :visible.sync="nodeContentDialog" width="50%" :close-on-click-modal="false">
      <div class="content">{{nodeInfo.properties.knowledgeContent}}</div>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="nodeContentDialog = false">关闭</el-button>
        </span>
      </template>
    </el-dialog>

  </div>
</template>

<script>
import VisGraph from '@/assets/js/visgraph.min.js'
import LayoutFactory from '@/assets/js/visgraph-layout.min.js'
import { config } from '@/assets/canvasConfig.js'
import { getNodes, getNodesRelative, deleteNode, getCategoies, updateNode, insertRelative,
  deleteLink, insertNode, insertLove, listUserLove } from '@/assets/api.js'
export default {
  components: {
    VisGraph,
    LayoutFactory
  },
  data () {
    return {
      // visGraph实例
      visGraph: null,
      // visGraph设置信息
      config,
      // visGraph创建知识联系的节点集和联系集
      graphData: {
        nodes: [],
        links: []
      },
      // 双击选中的节点信息
      nodeInfo: {
        properties: {}
      },
      // 双击选中的联系信息
      linkInfo: {},
      // 控制编辑节点对话框的显示
      editNodeDialog: false,
      // 节点在编辑对话框内的信息
      editNode: {
        id: '',
        classId: '',
        knowledgeName: '',
        knowledgeContent: '',
        size: '',
        knowledgeTag: '',
        color: ''
      },
      // 知识分类列表
      categories: [],
      // 判断当前是否进行联系知识操作(还存储父节点的ID)
      relativeNodeId: '',
      // 添加知识表单
      addNodeForm: {
        classId: '',
        knowledgeName: '',
        knowledgeContent: '',
        size: '',
        color: 'rgb(0, 0, 0)'
      },
      // 添加知识对话框是否开启
      addNodeDialog: false,
      // 目前所在分类的Id
      currentCateId: 0,
      // 是否显示知识详细信息
      nodeContentDialog: false,
      // 用户已收藏的知识
      collectList: [],
      loading: true
    }
  },
  methods: {
    // 获取所有的知识节点信息
    async getTagsList (id) {
      const {data: res} = await getNodes(id)
      this.graphData = {
        nodes: [],
        links: []
      }
      res.data.forEach(item => {
        let node = {properties: {}}
        node.id = item.id
        node.label = item.knowledgeName
        node.color = item.color
        node.properties.knowledgeTag = item.knowledgeTag
        node.properties.knowledgeContent = item.knowledgeContent
        node.properties.classId = item.classId
        node.size = item.size
        this.graphData.nodes.push(node)
      })
      this.getTagsRelativeList(id)
    },
    // 获取所有的知识联系信息
    async getTagsRelativeList (id) {
      const {data: res} = await getNodesRelative(id)
      res.data.forEach(item => {
        let link = {properties: {}}
        link.properties.id = item.id
        link.source = item.fatherId
        link.target = item.sonId
        this.graphData.links.push(link)
      })
      if (this.visGraph === null) {
        this.createCanvas()
      } else {
        this.refreshCanvas()
      }
    },
    // 创建canvas
    createCanvas () {
      this.visGraph = new VisGraph(document.getElementById('canvasMainId'), this.config)
      this.refreshCanvas()
    },
    // 刷新知识图谱
    refreshCanvas () {
      this.visGraph.clearAll()
      this.visGraph.drawData(this.graphData)
      this.layoutCanvas()
    },
    // 执行布局算法
    layoutCanvas () {
      var layout = new LayoutFactory(this.visGraph.getVisibleData()).createLayout('fastFR')
      layout.initAlgo()
      let i = 0
      while (i++ < 300) {
        layout.runLayout()
      }
      this.loading = false
    },
    // 显示知识简介
    nodeTags () {
      let string = this.nodeInfo.properties.knowledgeTag.replace(/\|/g, '&nbsp;&nbsp;')
      this.$confirm(string, this.nodeInfo.label, {
        confirmButtonText: '了解详细',
        cancelButtonText: '取消',
        dangerouslyUseHTMLString: true
      }).then(() => {
        this.nodeContentDialog = true
      }).catch(err => { console.log(err) })
      this.cancel()
    },
    // 显示知识操作栏(鼠标双击节点)
    mouseTwoClicked (event, node) {
      let nodeDialog = document.getElementById('nodeDialogId')
      nodeDialog.style.left = event.clientX + 'px'
      nodeDialog.style.top = event.clientY + 'px'
      nodeDialog.style.display = 'block'
      this.nodeInfo = node
      event.stopPropagation()
    },
    // 关闭知识操作栏
    cancel () {
      let nodeDialog = document.getElementById('nodeDialogId')
      nodeDialog.style.display = 'none'
    },
    // 关闭知识联系操作栏
    cancelLink () {
      let linkDialog = document.getElementById('linkDialogId')
      linkDialog.style.display = 'none'
    },
    // 删除知识操作
    async deleteNodeClick () {
      const {data: res} = await deleteNode(this.nodeInfo.id)
      if (res.code === 200) {
        let node = this.visGraph.findNode(this.nodeInfo.label)
        this.visGraph.deleteNode(node)
        this.visGraph.showAllNode()
        this.$message.success(res.msg)
      } else {
        this.$message.error(res.msg)
      }
      this.cancel()
      this.popoverNodeClose()
    },
    // 关闭删除知识的对话框
    popoverNodeClose () {
      this.$refs.popoverNode.doClose()
    },
    // 删除知识联系操作
    async deleteLinkClick () {
      const {data: res} = await deleteLink(this.linkInfo.properties.id)
      if (res.code === 200) {
        this.visGraph.deleteLink(this.linkInfo)
        this.visGraph.showAllNode()
        this.$message.success(res.msg)
      } else {
        this.$message.error(res.msg)
      }
      this.cancelLink()
      this.popoverLinkClose()
    },
    // 关闭删除知识联系的对话框
    popoverLinkClose () {
      this.$refs.popoverLink.doClose()
    },
    // 获取知识分类列表
    async getCategoriesList () {
      const {data: res} = await getCategoies()
      this.categories = res.data
    },
    // 编辑知识操作
    async editNoded () {
      if (this.editNode.color === null) {
        this.editNode.color = '0,0,0'
      } else {
        let color = this.editNode.color
        color = color.slice(4, color.length - 1)
        color = color.replace(/\s*/g, '')
        this.editNode.color = color
      }
      const {data: res} = await updateNode(this.editNode)
      if (res.code === 200) {
        this.$message.success(res.msg)
        this.getTagsList(this.currentCateId)
      } else {
        this.getTagsList(this.currentCateId)
        this.$message.error(res.msg)
      }
      this.editNodeDialog = false
    },
    // 打开知识编辑对话框
    showEditNodeDialog () {
      this.editNode.id = this.nodeInfo.id
      this.editNode.classId = this.nodeInfo.properties.classId
      this.editNode.knowledgeName = this.nodeInfo.label
      this.editNode.knowledgeContent = this.nodeInfo.properties.knowledgeContent
      this.editNode.size = this.nodeInfo.height
      this.editNode.knowledgeTag = this.nodeInfo.properties.knowledgeTag
      this.editNode.color = 'rgb(' + this.nodeInfo.fillColor.replace(/,/g, ', ') + ')'
      this.editNodeDialog = true
      this.cancel()
    },
    // 开启知识联系操作
    relative () {
      this.visGraph.begainAddLine(this.nodeInfo)
      this.relativeNodeId = this.nodeInfo.id
      this.cancel()
    },
    // 知识联系确认操作(看relativeNodeId是否为空)
    mouseClicked (event, node) {
      if (this.relativeNodeId) {
        this.nodeRelatived(node.id)
      } else {
        return false
      }
    },
    // 把知识联系存储到服务端
    async nodeRelatived (id) {
      const {data: res} = await insertRelative({
        fatherId: this.relativeNodeId,
        sonId: id
      })
      if (res.code === 200) {
        this.$message.success(res.msg)
        this.getTagsList(this.currentCateId)
      } else {
        this.$message.error(res.msg)
      }
      this.relativeNodeId = ''
    },
    // 打开知识联系操作栏(双击连线)
    mouseTowClickedOnRelative (event, link) {
      let linkDialog = document.getElementById('linkDialogId')
      linkDialog.style.left = event.clientX + 'px'
      linkDialog.style.top = event.clientY + 'px'
      linkDialog.style.display = 'block'
      this.linkInfo = link
    },
    // 关闭知识连接操作
    domMouseTwoClicked () {
      this.relativeNodeId = ''
    },
    // 添加知识操作
    async addNode () {
      if (this.addNodeForm.color === null) {
        this.addNodeForm.color = '0,0,0'
      } else {
        let color = this.addNodeForm.color
        color = color.slice(4, color.length - 1)
        color = color.replace(/\s*/g, '')
        this.addNodeForm.color = color
      }
      const {data: res} = await insertNode(this.addNodeForm)
      if (res.code === 200) {
        this.getTagsList(this.currentCateId)
        this.$message.success(res.msg)
      } else {
        this.$message.error(res.msg)
      }
      this.addNodeDialog = false
    },
    // 关闭添加知识对话框清空添加知识表单
    addDialogClose () {
      this.addNodeForm.classId = ''
      this.addNodeForm.knowledgeName = ''
      this.addNodeForm.knowledgeContent = ''
      this.addNodeForm.size = ''
      this.addNodeForm.knowledgeTag = ''
      this.addNodeForm.color = 'rgb(0, 0, 0)'
    },
    // 点击下拉菜单的内容跳转到相应分类的知识图谱
    handleCommand (command) {
      this.currentCateId = command
      this.getTagsList(this.currentCateId)
    },
    // 判断是否登录
    isLogined () {
      if (window.sessionStorage.token) {
        return true
      } else {
        return false
      }
    },
    // 判断权限是否足够
    isPower () {
      if (window.sessionStorage.admin === '1') {
        return true
      } else {
        return false
      }
    },
    // 收藏知识
    async collect () {
      if (!this.isLogined()) {
        this.$emit('needLogin')
        this.cancel()
        return false
      }
      const {data: res} = await insertLove(this.nodeInfo.id)
      if (res.code === 200) {
        this.$message.success(res.msg)
        this.getCollectList()
        this.cancel()
      } else {
        this.$message.error(res.msg)
      }
    },
    // 获取知识收藏
    async getCollectList () {
      const {data: res} = await listUserLove()
      if (res.code === 200) {
        this.collectList = res.data
      } else {
        this.$message.error(res.msg)
      }
    },
    // 查看节点是否已收藏
    isCollected () {
      let flag = 0
      this.collectList.forEach((item) => {
        if (item.id === this.nodeInfo.id) {
          flag = 1
        }
      })
      if (flag === 0) {
        return false
      } else {
        return true
      }
    }
  },
  created () {
    this.getCategoriesList()
    this.config.node.onClick = this.mouseClicked
    this.config.node.ondblClick = this.mouseTwoClicked
    this.config.node.onMouseDown = function (event, node) {
      event.stopPropagation()
    }
    if (this.isPower()) {
      this.config.link.ondblClick = this.mouseTowClickedOnRelative
    }
    if (this.$route.params.classId) {
      this.currentCateId = this.$route.params.classId
    }
    this.getTagsList(this.currentCateId)
    this.getCategoriesList()
    if (this.isLogined()) {
      this.getCollectList()
    }
  }
}
</script>

<style scoped>
  /* 整个组件的根组件样式 */
  .canvasMain {
    height: 98%;
    margin: 0;
    padding: 0;
  }
  /* 节点操作栏样式 */
  .nodeDialog {
    position: absolute;
    width: 80px;
    z-index: 5;
    display: none;
    border-radius: 10px;
    overflow: hidden;
    background: white;
  }
  .nodeDialog button {
    display: block;
    width: 80px;
    background: white;
    border: none;
    margin: 5px 2px;
  }
  .nodeDialog button:hover {
    background: skyblue;
  }
  .nodeDialog button:focus {
    outline:0;
  }
  /* 节点联系操作栏样式 */
  .linkDialog {
    position: absolute;
    width: 80px;
    z-index: 5;
    display: none;
    border-radius: 10px;
    overflow: hidden;
    background: white;
  }
  .linkDialog button {
    display: block;
    width: 80px;
    background: white;
    border: none;
    margin: 5px 2px;
  }
  .linkDialog button:hover {
    background: skyblue;
  }
  .linkDialog button:focus {
    outline:0;
  }
  /* 添加节点按钮样式 */
  .addNode {
    position: absolute;
    left: 210px;
    top: 70px;
    width: 70px;
    z-index: 5;
  }
  .content {
    min-height: 300px;
    max-height: 300px;
    overflow: scroll;
  }
  /* 禁用按钮 */
  .notButton {
    cursor: no-drop
  }
  .notButton:hover {
    background: none !important;
  }
</style>
